<?php

namespace App\Service;

use App\Entity\Money;
use App\Entity\MoneyLogType;
use App\Entity\MoneyPayOrder;
use App\Entity\MoneyType;
use App\Entity\User;
use App\Repository\ConfigRepository;
use App\Repository\MoneyConfigRepository;
use App\Repository\MoneyLogRepository;
use App\Repository\MoneyLogTypeRepository;
use App\Repository\MoneyPayOrderRepository;
use App\Repository\MoneyRepository;
use App\Repository\MoneyStaticRepository;
use App\Repository\MoneyTypeRepository;
use App\Repository\UserRepository;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\HttpFoundation\Request;

class PayService extends ServiceEntityRepository
{
    //支付参数设置
    const __PAY_TYPE_WECHAT__ = 100;
    const __PAY_TYPE_ALIPAY__ = 200;
    const __PAY_TYPE_UNION__ = 300;


    public $shopService;
    public $moneyService;
    public $orderService;
    public $taskService;
    public $userRepository;
    public $moneyRepository;
    public $moneyLogRepository;
    public $moneyTypeRepository;
    public $moneyConfigRepository;
    public $moneyStaticRepository;
    public $moneyLogTypeRepository;
    public $moneyPayOrderRepository;
    public $configRepository;

    public function __construct(
        ManagerRegistry $registry
        , ShopService $shopService
        , TaskService $taskService
        , MoneyService $moneyService
        , OrderService $orderService
        , UserRepository $userRepository
        , MoneyRepository $moneyRepository
        , MoneyLogRepository $moneyLogRepository
        , MoneyTypeRepository $moneyTypeRepository
        , MoneyConfigRepository $moneyConfigRepository
        , MoneyStaticRepository $moneyStaticRepository
        , MoneyLogTypeRepository $moneyLogTypeRepository
        , MoneyPayOrderRepository $moneyPayOrderRepository
        , ConfigRepository $configRepository
    )
    {
        parent::__construct($registry, Money::class);

        $this->shopService = $shopService;
        $this->taskService = $taskService;
        $this->moneyService = $moneyService;
        $this->orderService = $orderService;
        $this->userRepository = $userRepository;
        $this->moneyRepository = $moneyRepository;
        $this->moneyLogRepository = $moneyLogRepository;
        $this->moneyTypeRepository = $moneyTypeRepository;
        $this->moneyConfigRepository = $moneyConfigRepository;
        $this->moneyStaticRepository = $moneyStaticRepository;
        $this->moneyLogTypeRepository = $moneyLogTypeRepository;
        $this->moneyPayOrderRepository = $moneyPayOrderRepository;
        $this->configRepository = $configRepository;
    }

    /**
     * @param User $user
     * @param float $money
     * @param null $param
     * @param MoneyLogType|null $logType
     * @param MoneyType|null $moneyType
     * @return MoneyPayOrder
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function createPayOrder(User $user, float $money, MoneyType $moneyType = null, $param = null, MoneyLogType $logType = null)
    {
        $order = new MoneyPayOrder();
        $order->setUser($user)
            ->setMoney($money)
            ->setCreateAt(new \DateTime())
            ->setPayAt(null)
            ->setSn(uniqid($user->getId()))//回调唯一码
            ->setData(null)//回调数据
            ->setLogType($logType)
            ->setMoneyType($moneyType)
            ->setParam($param);
        $this->_em->persist($order);
        $this->_em->flush();
        return $order;
    }

    public function createInsureMoneyOrder(User $user, float $money)
    {
        $moneyTypeId = MoneyService::__MONEY_INSURE__;
        $moneyType = $this->moneyTypeRepository->find($moneyTypeId);
        return $this->createPayOrder($user, $money, $moneyType);
    }

    public function createPayParam($payType, MoneyPayOrder $payOrder)
    {//TODO 接入支付
        switch ($payType) {
            case self::__PAY_TYPE_WECHAT__:
                //微信支付
                break;
            case self::__PAY_TYPE_ALIPAY__:
                //支付宝支付
                break;
            case self::__PAY_TYPE_UNION__:
                //银联支付
                break;
        }
        return null;
    }

    public function dealWithPayCallBackInsure($sn)
    {
        $payOrder = $this->moneyPayOrderRepository->findOneBy(array("sn" => $sn));
        if ($payOrder->getPayAt()) {
            return false;//已经处理过了
        }
        $this->_em->beginTransaction();
        try {

            //修改订单支付信息
            $request = Request::createFromGlobals();
            $data = [
                "get" => $_GET
                , "post" => $_POST
                , "input" => "php://input"
                , "req_request" => $request->request->all()
                , "req_query" => $request->query->all()
                , "request" => $request
            ];
            $payOrder->setPayAt(new \DateTime())->setData($data);
            $this->_em->persist($payOrder);
            $this->_em->flush();

            //添加用户Money信息
            $user = $payOrder->getUser();
            $this->moneyService->addInsureMoney($user, $payOrder->getMoney());

            //添加用户《保证金标签》
//            $shop = $user->getShop();
//            var_dump( $shop->getTags()->containsKey(ShopService::__TAG_INSURE__) );
//            die();
//            if (!$shop->getTags()->containsKey(ShopService::__TAG_INSURE__)) {
//                //已经有此标签的不再处理，没有则新增
//                $this->shopService->addTagId($shop, ShopService::__TAG_INSURE__);
//            }
//            dd($shop);
            //分销机制分销奖励
            $moneys = $this->configRepository->getByK("SHARE_BONUS_PERCENT");
            $inviteArray = myExplodeNumbers($moneys);
            if (!is_array($inviteArray)) {
                $inviteArray = [];
            }
            $parentUser = $user->getParent();
            foreach ($inviteArray as $bonus) {
                if (!$parentUser) {
                    continue;
                }
                $inviteBonus = floor($payOrder->getMoney() * $bonus /100);
                //实际的积分记录
                $this->moneyService->mod($parentUser,$inviteBonus,MoneyService::__MONEY_JI_FEN__,161,"邀请返佣");

                //增加用户经验值
                $parentUser->addExpr($inviteBonus);
                $this->userRepository->dealWithLevel($parentUser);
                $parentUser = $parentUser->getParent();
            }

        } catch (\Exception $exception) {
            $this->_em->rollback();
            throw $exception;
        }
        $this->_em->commit();

    }


    /**
     * 检查支付类型是否合法
     * @param $payType
     * @return bool
     */
    public function checkPayType($payType)
    {
        switch ($payType) {
            case self::__PAY_TYPE_WECHAT__:
                $payType = self::__PAY_TYPE_WECHAT__;
                break;
            case self::__PAY_TYPE_ALIPAY__:
                $payType = self::__PAY_TYPE_ALIPAY__;
                break;
            case self::__PAY_TYPE_UNION__:
                $payType = self::__PAY_TYPE_UNION__;
                break;
            default:
                return false;
        }
        return true;
    }


    public function dealWithCallBackTaskHire($sn)
    {
        $payOrder = $this->moneyPayOrderRepository->findOneBy(array("sn" => $sn));
        if ($payOrder->getPayAt()) {
            return false;//已经处理过了
        }
        $request = Request::createFromGlobals();
        $data = [
            "get" => $_GET
            , "post" => $_POST
            , "input" => "php://input"
            , "req_request" => $request->request->all()
            , "req_query" => $request->query->all()
            , "request" => $request
        ];
        $this->_em->beginTransaction();
        try {
            //修改订单支付信息
            $payOrder->setPayAt(new \DateTime())->setData($data);
            $this->_em->persist($payOrder);
            $this->_em->flush();
            $param = $payOrder->getParam();
            $taskId = $param["taskId"];
            $voteId = $param["voteId"];

            $rst = $this->taskService->dealWithTaskPay($taskId,$voteId);
            if (!$rst) {

            }

        } catch (\Exception $exception) {
            $this->_em->rollback();
            $data["error"] = true;
            $payOrder->setData($data);
            $this->_em->persist($payOrder);
            $this->_em->flush();
            throw $exception;
        }
        $this->_em->commit();
    }



    public function dealWithCallBackUserCharge($sn)
    {
        $payOrder = $this->moneyPayOrderRepository->findOneBy(array("sn" => $sn));
        if ($payOrder->getPayAt()) {
            return false;//已经处理过了
        }
        $request = Request::createFromGlobals();
        $data = [
            "get" => $_GET
            , "post" => $_POST
            , "input" => "php://input"
            , "req_request" => $request->request->all()
            , "req_query" => $request->query->all()
            , "request" => $request
        ];
        $this->_em->beginTransaction();
        try {
            //修改订单支付信息
            $this->moneyService->mod($payOrder->getUser(),$payOrder->getMoney(),MoneyService::__MONEY_XIAN_JIN__,101,"在线充值");
        } catch (\Exception $exception) {
            $this->_em->rollback();
            throw $exception;
        }
        $this->_em->commit();
    }


    public function dealWithCallBackOrder($sn)
    {
        $payOrder = $this->moneyPayOrderRepository->findOneBy(array("sn" => $sn));
        if ($payOrder->getPayAt()) {
            return false;//已经处理过了
        }
        $request = Request::createFromGlobals();
        $data = [
            "get" => $_GET
            , "post" => $_POST
            , "input" => "php://input"
            , "req_request" => $request->request->all()
            , "req_query" => $request->query->all()
            , "request" => $request
        ];
        $this->_em->beginTransaction();
        try {
            //修改订单支付信息
            $payOrder->setPayAt(new \DateTime())->setData($data);
            $this->_em->persist($payOrder);
            $this->_em->flush();
            $param = $payOrder->getParam();
            $orderId = $param["orderId"];

            $rst = $this->orderService->dealWithOrderPay($orderId);
            if (!$rst) {

            }

        } catch (\Exception $exception) {
            $this->_em->rollback();
            $data["error"] = true;
            $payOrder->setData($data);
            $this->_em->persist($payOrder);
            $this->_em->flush();
            throw $exception;
        }
        $this->_em->commit();
    }


    public function uniCallBack($sn,$from="")
    {
        switch ($from) {
            case "insure":
                $this->dealWithPayCallBackInsure($sn);
                break;
            case "taskhire":
                $this->dealWithCallBackTaskHire($sn);
                break;
            case "order":
                $this->dealWithCallBackOrder($sn);
                break;
            case "charge":
                $this->dealWithCallBackUserCharge($sn);
                break;
        }
    }


}